
#include <BLabel>
#include <BGridLayout>
#include <BVBoxLayout>
#include <BHBoxLayout>
#include <BGroupBox>
#include <BBody>

#include "StringUtils.h"
#include "BodyBoard.h"

BodyBoard::BodyBoard(BWidget* parent) : BGroupBox(parent)
{
	this->setTitle("BBody");
	this->setTitleAlign(Align_Center);

	BGridLayout* gridLayout = new BGridLayout();
	{
		_positionEdit = new BLineEdit();
		_rotateEdit = new BLineEdit();

		_massSpinBox = new BRealSpinBox();
		_massSpinBox->setSuffix("kg");
		_massSpinBox->setSuffixAlign(Align_RightCenter);

		_frictionSpinBox = new BRealSpinBox();
		_frictionSpinBox->setSuffix("[0~1]");
		_frictionSpinBox->setSuffixAlign(Align_RightCenter);

		_restitutionSpinBox = new BRealSpinBox();
		_restitutionSpinBox->setSuffix("[0~1]");
		_restitutionSpinBox->setSuffixAlign(Align_RightCenter);

		gridLayout->addWidget(0, 0, new BLabel("position"));
		gridLayout->addWidget(0, 1, _positionEdit);
		gridLayout->addWidget(1, 0, new BLabel("rotate"));
		gridLayout->addWidget(1, 1, _rotateEdit);
		gridLayout->addWidget(2, 0, new BLabel("mass"));
		gridLayout->addWidget(2, 1, _massSpinBox);
		gridLayout->addWidget(3, 0, new BLabel("friction"));
		gridLayout->addWidget(3, 1, _frictionSpinBox);
		gridLayout->addWidget(4, 0, new BLabel("restitution"));
		gridLayout->addWidget(4, 1, _restitutionSpinBox);
	}

	BGridLayout* forceLayout = new BGridLayout();
	{
		_forceXSpinBox = new BRealSpinBox();
		_forceYSpinBox = new BRealSpinBox();
		_forceZSpinBox = new BRealSpinBox();
		forceLayout->addWidget(0, 0, new BLabel("Force X"));
		forceLayout->addWidget(0, 1, _forceXSpinBox);
		forceLayout->addWidget(1, 0, new BLabel("Y"));
		forceLayout->addWidget(1, 1, _forceYSpinBox);
		forceLayout->addWidget(2, 0, new BLabel("Z"));
		forceLayout->addWidget(2, 1, _forceZSpinBox);
	}

	BVBoxLayout* vlayout = new BVBoxLayout(this);
	vlayout->addLayout(gridLayout);
	vlayout->addLayout(forceLayout);

	connect(this, Signal_AssetChanged, &BodyBoard::slotAssetChanged);

	connect(_positionEdit, Signal_EditFinished, &BodyBoard::slotPositionEditFinished);
	connect(_rotateEdit, Signal_EditFinished, &BodyBoard::slotRotateEditFinished);
	connect(_massSpinBox, Signal_EditFinished, &BodyBoard::slotMassEditFinished);

	connect(_frictionSpinBox, Signal_EditFinished, &BodyBoard::slotFrictionEditFinished);
	connect(_restitutionSpinBox, Signal_EditFinished, &BodyBoard::slotRestitutionEditFinished);

	connect(_forceXSpinBox, Signal_EditFinished, &BodyBoard::slotForceEditFinished);
	connect(_forceYSpinBox, Signal_EditFinished, &BodyBoard::slotForceEditFinished);
	connect(_forceZSpinBox, Signal_EditFinished, &BodyBoard::slotForceEditFinished);
}
BodyBoard::~BodyBoard()
{

}

void BodyBoard::slotAssetChanged(BObject* object, const BValue& value)
{
	if (BNode* node = value)
	{
		const BVector& position = node->position();
		_positionEdit->setText(StringFromVector(position));
		_rotateEdit->setText(StringFromQuater(node->rotate()));
	}
	if (BBody* body = value)
	{
		_massSpinBox->setValue(body->mass());
		_frictionSpinBox->setValue(body->friction());
		_restitutionSpinBox->setValue(body->restitution());
		const BVector& force = body->force();
		_forceXSpinBox->setValue(force.x());
		_forceYSpinBox->setValue(force.y());
		_forceZSpinBox->setValue(force.z());
	}
}

void BodyBoard::slotPositionEditFinished(BObject* object, const BValue& value)
{

}
void BodyBoard::slotRotateEditFinished(BObject* object, const BValue& value)
{

}

void BodyBoard::slotMassEditFinished(BObject* object, const BValue& value)
{
	if (BBody* body = this->asset())
	{
		BReal mass = value;
		body->setMass(mass);
	}
}
void BodyBoard::slotFrictionEditFinished(BObject* object, const BValue& value)
{
	if (BBody* body = this->asset())
	{
		BReal friction = value;
		body->setFriction(friction);
	}
}
void BodyBoard::slotRestitutionEditFinished(BObject* object, const BValue& value)
{
	if (BBody* body = this->asset())
	{
		BReal restitution = value;
		body->setRestitution(restitution);
	}
}
void BodyBoard::slotForceEditFinished(BObject* object, const BValue& value)
{
	if (BBody* body = this->asset())
	{
		BReal forceX = _forceXSpinBox->value();
		BReal forceY = _forceYSpinBox->value();
		BReal forceZ = _forceZSpinBox->value();
		body->setForce(forceX, forceY, forceZ);
	}
}
